2W - 테라폼으로 환경 구성 및 VPC 연결

개요

본 글은 다음의 내용을 설명하고, 이를 위한 실습을 진행한다.

앞으로의 실습을 위해 간단하게 환경을 구축하는 방법을 제시하는 노트이다.
이를 바탕으로 본격적으로 eks 네트워크에 대한 분석을 진행할 예정이다.
그래서 이번 노트에서는 다양한 aws의 리소스들에 대한 사전지식을 먼저 다룬다.

사전 지식

VPC

Virtual Private Cloud(VPC)는 AWS에서 제공하는 사설 네트워크 망이다.
aws에서 거의 기본이 되는 리소스이기 때문에 자세히 다루지는 않으나, 다만 vpc 간의 트래픽 연결을 하는 방법에 대해 조금 알아보자.

VPC Peering


VPC를 1대1로 연결한다.
세팅이 무척 쉽고, 이 커넥션을 만드는 것 자체는 비용이 나가지 않는다.
또한 같은 az에서의 트래픽에 대해서는 비용이 발생하지 않는다.
근데 요런 특징들이 있다.

이번 실습에서, 다른 vpc의 인스턴스에 접근하기 위해 사용할 예정이다.


vpc 내의 호스팅되는 서비스의 특정 엔드포인트만 뚫어서 다른 vpc에 eni로 연결해서 제공하는 기술이다.[1]
어떤 서비스이든 이걸 이용하면 해당 서비스로 연결할 수 있는 네트워크 인터페이스가 붙고, 이 인터페이스에 서브넷의 프라이빗 ip가 할당된다.
(달리 말하면 vpc에 사용 가능한 ip가 없다면 문제가 생길 것이다.)
EKS에서 컨트롤 플레인의 vpc가 사용자의 데이터 플레인 vpc에 연결될 때 바로 이러한 기능을 사용하는 것이다.

이번에 이걸 한번 이용해볼 텐데, 아래에서 자세히 보자.

CloudTrail

image.png
클라우드트레일4.RESOURCE/KNOWLEDGE/AWS/AWS 계정에서 발생하는 각종 이벤트를 보는 리소스이다.
리소스가 생성된다거나, 조작되거나, 누가 접근했을 때라던가, 하는 모든 이벤트를 볼 수 있는 툴이라 보면 되겠다.
클라우드트레일은 처음 계정이 만들어지는 순간부터 항상 존재하며, 발생한 event history를 볼 수 있다.
이 히스토리를 보는 것은 무료지만, 이 이벤트들은 90일이 지나면 삭제되니 저장이 필요한 이벤트라면 별도의 관리가 필요하다.

trail

event history는 말 그대로 여태 일어난 이벤트를 보고, 따로 로컬에 저장하는 작업만 할 수 있다.
그러나 클라우드 트레일을 더 효과적으로 쓰는 방법 중 하나는 이것을 이용해서 메트릭을 만들어 분석하거나, 특정 이벤트에 대해 어떤 동작을 하는 설정을 추가하는 것이다.
이때 트레일(클라우드 트레일의 트레일..)을 만들어서 설정을 하는 것이 가능하다.
event history로 보는 내용들을 S3에 저장하여 보는 방식으로, 체계적으로 관리하는 event history라고도 볼 수 있겠다.
아래에서 볼 [[#EventBridge]]에 특정 이벤트를 넘기기 위해서는 꼭 세팅을 해야 한다.
(기본 event history는 이벤트 브릿지로 넘어가지 않는다는 것을 몰라서 한참을 헤맸더랬다..)

EventBridge

이벤트브릿지는 발생한 이벤트에 따라 어떤 어플리케이션이나 프로세스를 실행할 수 있도록 설정하는 트리거 역할을 하는 리소스이다.

이벤트 브릿지는 기본적으로 버스라는 것을 두고, 그 뒤에 각종 규칙을 생성하여 이벤트를 타겟으로 보낸다.
가령 내가 로그인하는 이벤트를 걸리도록 규칙을 쓰고, 특정 람다 함수를 발동시키는 식의 운용이 가능하다.
소위 이벤트 드리븐 아키텍쳐를 만들 수 있는 서버리스 리소스!
버스에 어떻게 규칙을 작성하는 지는 실습에서 보도록 하겠다.

아무런 설정을 하지 않더라도 기본 버스(default bus)가 존재하며, 이 버스는 클라우드트레일에서 발생하는 기본적인 관리 이벤트를 전부 받도록 되어 있다.

Lambda

람다는 필요한 만큼만 원하는 때에 동작을 수행하는 서버리스 리소스이다.
이거 정리하다간 숨 넘어갈 것 같아서 이 정도로만 정리해둔다!

실습 진행

이제 본격적으로 실습을 진행해보자.
위에서 이야기했듯, 이번 노트는 이 실습 환경을 구성하는 것 자체가 주목적이다.

구성도

실습하고자 하는 환경은 이렇다.
image.png
eks 클러스터와 운영하는 환경이 따로 있는 상황이다.
이런 상황은 실무 운영 환경에서 충분히 있을 수 있다.
기존에 서비스하던 아키텍쳐에서 eks로 마이그레이션을 진행할 때, 별도의 vpc를 두고 세팅하는 방식은 유용할 것이다.
또한 다른 회사와 협약을 통해 운영 업무를 하고 있는 상황일 때도, 이러한 구조를 택할 수 있다.
구체적으로 이러한 조건을 걸고자 한다.

스터디에서 제공해준 클라우드 포메이션, eks.yaml 파일을 토대로 같은 환경이 구성하는 것이 일차 목표이다.
그러나 여기에 나는 추가적으로 구성을 하고자 한다.
운영 vpc에서 클러스터 액세스 엔드포인트에 프라이빗 모드로 접근 가능하게 만드는 것.[2]
현재 아키텍쳐에서는 운영 호스트에서 클러스터 조작을 하려면 퍼블릭 엔드포인트를 사용해야 한다.
(물론 피어링을 했기 때문에 직접 프라이빗 엔드포인트 주소에 대해 hosts 파일을 작성하는 식으로 활용할 수는 있다)

Amazon Route53의 프라이빗 호스팅 존에 운영 vpc를 추가하여 엔드포인트에 대한 dns 질의가 알아서 프라이빗 주소를 나타내도록 할 수 있다면 좋겠지만, 클러스터 주소에 대한 route53은 aws가 관리하고 있으며 관련한 커스텀 기능을 제공하지 않는다.
(내 생각에는 추후에는 제공할 가능성도 있다)
|1500
그래서 이런 식으로 추가적인 리소스를 들여, 프라이빗 엔드포인트로 통신을 할 수 있도록 만들어주고자 한다.
다른 vpc에서도 클러스터 엔드포인트 도메인 주소에 대해 eks owned eni의 ip가 나오도록 세팅하는 것이 주골자이다.
이를 위해 다음의 리소스를 세팅한다.

이렇게 아키텍쳐를 만들게 되면 운영 vpc에서 어떻게 클러스터와 통신을 하게 되는가?

추가 세팅

..까지가 원래 해당 방법을 제공한 글의 내용인데, 나는 여기에 조금의 설정을 더 해줬다.
이유인즉슨, eventbridge로 이벤트가 전달되기 위해서는 트레일이 하나 있어야 하기 때문에 해당 리소스를 만드는 과정도 추가하게 됐다.
다만 대부분의 프라이빗 링크 세팅은 해당 자료를 대부분 참고했다는 점을 먼저 밝힌다.

테라폼 구성

이런 환경을 구성하기 위해 나는 다음과 같이 세팅했다.
image.png
각 파일을 설명하면 대충 이렇다.

terraform init
terrafrom apply -target=module.nlb -target=module.eventbridge -target=aws_cloudtrail.cloudtrail ---auto-approve
terrafrom apply  ---auto-approve

실제 코드는 레포지토리에 담았고, 받아서 이렇게 실행하면 된다.[4]
아직 테라폼이 익숙치 않아서 조금 더럽게 짠 것 같긴 하지만..
아무튼 각각의 파일에서 어려웠던, 설명할 만한 부분들을 언급해보겠다.

image.png
모든 인스턴스에 연결할 때 사용할 키는 ssh.tf로 따로 빼뒀다.

image.png
오퍼레이터 ec2는 ssm 연결이 가능하도록 인스턴스 프로파일을 넣어줬다.
userdata에는 각종 툴과 세팅을 미리 넣어두었다.

이밖에 보안 그룹과 피어링 연결에 대한 코드를 작성했다.

image.png
이 파일에서는 eks를 설정하는 코드를 넣었다.
이때 eks 설정에서는 일단 보안 그룹으로 nlb에서 들어오는 트래픽과, 운영 ec2에서 오는 요청을 허용하도록 해두었다.
이 설정 자체는 api 서버로 가는 요청을 가능하게 만든다.
여기 nlb 트래픽을 허용하기 위해 data.dns_a_record_set.nlb를 사용하는데, 이것은 privatelink.tf에서 볼 것이다.
image.png
테라폼 eks 모듈에서는 별도로 클러스터 보안 그룹을 설정할 수 있도록 지원하지 않는다.
그래서 eks가 생성된 이후 기본 보안 그룹을 받아오고 운영 ec2의 트래픽을 받을 수 있도록 설정한다.
이를 통해 운영 ec2에서 워커 노드로 ssh 접근을 할 수 있게 됐다.

managed_node_groups.tf

image.png
관리형 노드 그룹은 따로 코드를 분리해서 작성했는데, 이 방식은 그다지 좋지 않은 것 같다.
eks 모듈 중 서브 모듈로서 있는 파일의 내용을 참조하여 local 변수로 만들었는데, 이렇게 한 이유는 주 모듈에서 서브 모듈을 참조하지 않고 관계가 역전되는 것이 맘에 들지 않기 때문이다.
다만 그렇다고 아예 local 변수로 만들어버리는 것은 검증을 어렵게 만드는 자충수인 것 같아서 이건 언젠가 수정할 듯..

image.png
이제 본격적으로 운영 vpc에서 프라이빗 주소로 통신할 수 있도록 프라이빗 링크를 연결하는 세팅을 보자.
먼저 nlb는 ip를 타겟그룹으로 둔다.
실제 타겟으로는 아직 아무 값도 없으며, eks가 구축되면 람다를 통해 값이 들어가게 될 것이다.
image.png
여기 이 값이 클러스터 보안 그룹으로 추가되는 도메인인데, nlb가 프로비저닝돼야 이 값이 정해지기 때문에 테라폼을 설치에 순서를 둬야 한다..
아마 더 나은 방법이 있지 않을까 생각만 하고 있다.
image.png
이 nlb를 엔드포인트 서비스로 노출시키고, 운영 vpc에서 엔드포인트를 받는다.
image.png
그 다음엔 route53을 설정한다.
클러스터 엔드포인트를 도메인으로 등록하고, 별칭으로는 프라이빗 링크로 뚫린 도메인을 넣어준다.
이를 통해 운영 vpc에서 클러스터 엔드포인트에 대한 질의를 날리면 프라이빗 링크 ip가 반환되는 것이다.

이 다음에는 람다와 이벤트 브릿지 설정이다.
image.png
람다는 이렇게 설정한다.
딱히 테라폼 코드로 볼 건 없고, 람다로 실행하는 함수를 보자.
image.png
로드밸런서에 aws api 요청을 날려서 private ip를 타겟그룹에 등록한다.
event로 들어오는 인자에 해당 ip가 담기기에 이런 식의 설정이 가능하다.
image.png
불필요한 엔드포인트를 삭제하는 람다 함수는 15분마다 실행되도록 세팅됐다.
먼저 타겟그룹에서 헬스체크에 실패한 ip 리스트를 모으고, vpc의 엔드포인트 중 eks 소유의 eni와 비교한다.
헬스체크에 실패한 ip가 eks의 eni에 없다면 해당 ip는 이제 유효하지 않다는 뜻이므로 등록 해제하는 절차를 밟게 된다.
image.png
이벤트브릿지 모듈에 각 함수 발동 규칙을 걸어둔다.
타겟 그룹에 ip를 등록하는 규칙의 경우, CreateNetworkInterface이벤트 이름을 조건으로 건다.
이때 단순히 이것으로만 조건을 걸면 문제가 되는 것이, 인스턴스가 생기고 거기에 네트워크 인터페이스가 연결되는 관련한 모든 이벤트에 발동이 걸리게 된다.
그렇기 때문에 description으로 추가 필터를 건다.
추가적으로 소스 ip주소도 필터로 걸어 어디에서 해당 이벤트가 발생하는지도 명확히 한다.

삭제를 하는 함수는 15분마다 발동된다.
아직 이벤트브릿지와 람다를 쓰는 게 익숙하지 않아 참고 자료를 그대로 따라한 것이긴 한데, 이것도 사실 이벤트를 가지고 처리를 할 수 있지 않을까 싶다.

image.png
event history만 있으면 무조건 이벤트브릿지로 이벤트가 보내질 줄 알고 삽질하다가 결국 만든 트레일.
버켓을 지정하고 관리 이벤트들을 저장한다.
이 부분에서 조금 어려웠던 건 순서 의존 설정 때 s3 버켓 자체가 아니라 버켓 정책을 지정해야 한다는 것...

구축 및 테스트

terraform init
terrafrom apply -target=module.nlb -target=module.eventbridge -target=aws_cloudtrail.cloudtrail ---auto-approve
terrafrom apply  ---auto-approve

이제 본격적으로 해당 환경을 확인하고 테스트해보자.

엔드포인트를 위한 세팅

image.png
이벤트 브릿지를 들어가보면, eks-api-endpoint-create-rule이라는 룰이 추가된 것을 볼 수 있다.
네트워크 인터페이스 생성 이벤트 중, eks owned eni가 생성되는 이벤트를 포착하면 이를 람다함수로 보내줄 것이다.
image.png
포착되는 것은 바로 이 이벤트로, cloudtrail event history에 들어가서 쉽게 확인할 수 있다.
image.png
해당 이벤트는 보다시피 responseElements.privateIpAddress 필드에 eni의 프라이빗 주소를 가지고 있기에, 람다 함수는 이것은 로드밸런서의 대상 그룹에 넣어준다.
image.png
성공적으로 로드밸런서의 대상그룹에 들어가는 것이 확인되며, 헬스체크도 원활하게 이뤄지고 있다.
image.png
네트워크 인터페이스 생성 이벤트는 노드 그룹 차원에서도, vpc cni 차원에서도 이뤄지기에 이런 이벤트까지 포함하지 않도록 하는 것이 중요하다고 할 수 있다.
image.png
이건 route53에 추가된 hoted zone 세팅이다.
클러스터 액세스 엔드포인트에 대해 CNAME레코드마냥 다른 도메인을 반환하도록 되어있다.
alias 기능을 활용하는 것이라 실제 레코드 타입은 A레코드.

운영 호스트 세팅

image.png
운영 호스트는 vpc의 보안 그룹과 내 로컬에서 접속하기 위한 보안그룹을 할당받았다.
image.png
eks의 primary 보안그룹은 운영 vpc 보안그룹의 인바운드를 허용하고 있기 때문에, 모든 노드에 대한 접근이 가능해진다.
또 eks owned eni에 대해서도 운영 vpc의 보안그룹을 뚫어뒀기에 api 서버로의 통신도 무리없이 가능할 것이다.

운영 호스트 접속

endpoint = "https://9900294EF382AB305C81DD3138BD1D9B.gr7.ap-northeast-2.eks.amazonaws.com"
operator_ec2_id = "i-02e396b50737c4e88"
operator_ec2_ip = "43.201.0.83"
ssh_command = "ssh -i ./eks-key.pem ec2-user@43.201.0.83"
ssm_command = "aws ssm start-session --target i-02e396b50737c4e88"

테라폼 프로비저닝이 완료된 이후 편하게 접속할 수 있도록 커맨드를 미리 꺼내두도록 세팅했다.
ssm쪽은 사실 세팅을 완벽하게 하지는 않아서 접속은 가능하나, 명령어 설치는 되어있지 않다.
image.png
호스트에서 엔드포인트로 도메인 질의를 날리면 실제로는 nlb가 서비스인 인터페이스 엔드포인트의 프라이빗 주소가 반환된다.
여기로 트래픽을 보내면 자연스럽게 eks owned eni로 통신이 흐르게 된다.

tcpdump -i ens5 -nn dst port 443

그럼 실제로 어디로 통신이 가는지도 확인해보도록 하자.
443으로 나가는 모든 패킷을 훔쳐보자!
(참고로 이렇게 하면 ssm-agent가 systems manager한테 지속적으로 상태를 업데이트하는 요청도 잡힌다.)
image.png
kubectl을 사용하는 명령어를 치자, 위에서 확인한 엔드포인트로 통신이 이뤄지는 것을 확인할 수 있다.
image.png
각 노드로 ssh 접속을 하는 것도 가능하다!
클러스터 보안그룹을 뚫어두고, vpc peering을 했기 때문에 가능한 것이다.

결론

테라폼

테라폼을 사용하면 원하는 환경을 편하게 프로비저닝할 수 있다.
벤더 종속성에서 상대적으로 자유롭고, 프로비저닝에 필요한 많은 설정을 자동화할 수 있다.
또한 항상 같은 상황을 구축하는 것을 보장할 수 있는, Immutable Infrastructure 환경을 만드는 데 큰 도움을 준다.
앞으로도 실습을 진행하며 테라폼 코드를 발전시키며 임하고자 한다.

그러나 당부할 사항은, 함부로 남이 만든 모듈을 사용하는 것은 지양하는 것이 좋다는 것이다.
aws에서 만들고 관리하는 각종 모듈을 활용하는 것이 코드를 줄이고 관리 용이성을 증대시킬 것이라고 생각했다.
image.png
그러나 막상 해보니 어려운 점이 두 가지 있었다.

처음에는 모듈을 사용하면 내가 아직 잘 모르는 리소스를 활용할 때 큰 도움을 얻을 수 있겠다고 생각했지만, 막상 보면 결국 그 모듈을 세팅하기 위해 필요한 모든 리소스를 알고 싶지 않아도 알게 되더라.
이럴 거라면 모듈을 직접 쓰는 것보다는 모듈의 코드를 보고 비슷하게 따라해서 나만의 모듈을 만드는 것이 훨씬 현명하겠다는 것이 내 생각이다.
과거에 테라폼을 제대로 써보지 않던 시절에는 테라폼은 무적권 좋다!라고만 생각했지만..
물론 지금도 그 생각에는 큰 변화는 없지만 최소한 사용에 있어서 주의 깊게 접근해야 한다는 생각이다.
아마 나중에 디벨롭을 시킨다면 모듈 의존성을 줄이고 전부 내 코드로 바꾸는 작업을 하지 않을까 싶다.

다른 VPC에서 프라이빗 엔드포인트로의 접근

이번 실습에서 주되게 신경 쓴 부분은 운영 환경에서 자유롭게 프라이빗 엔드포인트를 활용할 수 있도록 하는 것이었다.
이를 위해 별도의 route53 도메인을 등록하고, 로드밸런서를 프라이빗 링크로 뚫는 추가적인 작업을 했다.
언젠가 aws에서 api서버 엔드포인트 자체를 인터페이스 엔드포인트로 제공하는 기능을 추가할 가능성이 있는데, 그전까지 이 방법은 안전한 통신을 보장하는 수단이 되어줄 것이다.

이전 글, 다음 글

다른 글 보기

이름 index noteType created
1W - EKS 설치 및 액세스 엔드포인트 변경 실습 1 published 2025-02-03
2W - 테라폼으로 환경 구성 및 VPC 연결 2 published 2025-02-11
2W - EKS VPC CNI 분석 3 published 2025-02-11
2W - ALB Controller, External DNS 4 published 2025-02-15
3W - kubestr과 EBS CSI 드라이버 5 published 2025-02-21
3W - EFS 드라이버, 인스턴스 스토어 활용 6 published 2025-02-22
4W - 번외 AL2023 노드 초기화 커스텀 7 published 2025-02-25
4W - EKS 모니터링과 관측 가능성 8 published 2025-02-28
4W - 프로메테우스 스택을 통한 EKS 모니터링 9 published 2025-02-28
5W - HPA, KEDA를 활용한 파드 오토스케일링 10 published 2025-03-07
5W - Karpenter를 활용한 클러스터 오토스케일링 11 published 2025-03-07
6W - PKI 구조, CSR 리소스를 통한 api 서버 조회 12 published 2025-03-15
6W - api 구조와 보안 1 - 인증 13 published 2025-03-15
6W - api 보안 2 - 인가, 어드미션 제어 14 published 2025-03-16
6W - EKS 파드에서 AWS 리소스 접근 제어 15 published 2025-03-16
6W - EKS api 서버 접근 보안 16 published 2025-03-16
7W - 쿠버네티스의 스케줄링, 커스텀 스케줄러 설정 17 published 2025-03-22
7W - EKS Fargate 18 published 2025-03-22
7W - EKS Automode 19 published 2025-03-22
8W - 아르고 워크플로우 20 published 2025-03-30
8W - 아르고 롤아웃 21 published 2025-03-30
8W - 아르고 CD 22 published 2025-03-30
8W - CICD 23 published 2025-03-30
9W - EKS 업그레이드 24 published 2025-04-02
10W - Vault를 활용한 CICD 보안 25 published 2025-04-16
11W - EKS에서 FSx, Inferentia 활용하기 26 published 2025-04-18
11주차 - EKS에서 FSx, Inferentia 활용하기 26 published 2025-05-11
12W - VPC Lattice 기반 gateway api 27 published 2025-04-27

관련 문서

이름 noteType created
EKS, ECS 비교 knowledge 2024-11-03
Amazon Fargate knowledge 2024-11-03
Amazon Elastic Kubernetes Service knowledge 2025-02-01
Terraform knowledge 2025-02-05
eksctl knowledge 2025-02-06
Karpenter knowledge 2025-03-04
EKS Automode knowledge 2025-04-23
E-파드 마운팅 recursiveReadOnly topic/explain 2025-02-27
E-이스티오 가상머신 통합 topic/explain 2025-06-01
S-vpc 설정이 eks 액세스 엔드포인트에 미치는 영향 topic/shooting 2025-02-07
S-테라폼으로 헬름 설치할 때 네임스페이스 이슈 topic/shooting 2025-04-07
T-마운트 전파 Bidirectioal topic/temp 2025-02-28

참고


  1. https://docs.aws.amazon.com/ko_kr/vpc/latest/userguide/endpoint-services-overview.html ↩︎

  2. https://aws.amazon.com/ko/blogs/containers/enable-private-access-to-the-amazon-eks-kubernetes-api-with-aws-privatelink/ ↩︎

  3. https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html ↩︎

  4. https://github.com/Zerotay/AEWS-3th/tree/main/2week/terraform ↩︎